package com.xlh.virtualization.controller;

import com.xlh.aop.PreAcquireLock;
import com.xlh.common.Result;
import com.xlh.security.SpringSecurityUserInfoHolder;
import com.xlh.security.UserInfoHolder;
import com.xlh.virtualization.domain.ContainerContext;
import com.xlh.virtualization.domain.ExperimentContext;
import com.xlh.virtualization.po.ImageAllocationCourseUpdatePO;
import com.xlh.virtualization.po.ImageAllocationImageUpdatePO;
import com.xlh.virtualization.po.ImageAllocationUpdatePO;
import com.xlh.virtualization.service.ContainerService;
import com.xlh.virtualization.service.ExperimentService;
import com.xlh.virtualization.service.ImageAllocationService;
import com.xlh.virtualization.vo.ImageAllocationContainerVO;
import com.xlh.virtualization.vo.ImageAllocationCourseVO;
import com.xlh.virtualization.vo.ImageAllocationVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

import static com.xlh.virtualization.constant.ContextTypeEnum.*;
import static com.xlh.virtualization.constant.ExperimentConstant.*;

/**
 * @author cheer
 */
@Api("课程镜像分配")
@RestController
@RequestMapping("/image-allocation/course")
public class ImageAllocationCourseController extends BaseImageAllocationController {

    @Autowired
    public ImageAllocationCourseController(UserInfoHolder userInfoHolder, ImageAllocationService imageAllocationService,
                                           ExperimentService experimentService, ContainerService containerService) {
        super.userInfoHolder = userInfoHolder;
        super.imageAllocationService = imageAllocationService;
        super.experimentService = experimentService;
        super.containerService = containerService;
    }

    @ApiOperation("查询课程镜像分配")
    @GetMapping("/{courseId}/{chapterId}")
    public Result<ImageAllocationVO> getImageAllocation(@PathVariable("courseId") Long courseId,
                                                        @PathVariable("chapterId") Long chapterId) {
        return super.getImageAllocation(chapterId);
    }

    @ApiOperation("课程保存镜像分配")
    @PostMapping("/{chapterId}")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result updateImageAllocation(@PathVariable("chapterId") Long chapterId,
                                        @RequestBody @Valid ImageAllocationUpdatePO imageAllocationUpdatePO) {
        return super.updateImageAllocation(chapterId, imageAllocationUpdatePO);
    }

    @ApiOperation("课程批量保存镜像分配")
    @PostMapping
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result updateImageAllocation(@RequestBody @Valid ImageAllocationCourseUpdatePO imageAllocationCourseUpdatePO) {
        for (Long chapterId : imageAllocationCourseUpdatePO.getChapterIds()) {
            super.updateImageAllocation(chapterId, imageAllocationCourseUpdatePO);
        }
        return Result.success();
    }

    @ApiOperation("课程解除镜像分配")
    @PostMapping("/delete")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result deleteImageAllocation(@RequestBody List<Long> chapterIds) {
        for (Long chapterId : chapterIds) {
            super.deleteImageAllocation(chapterId);
        }
        return Result.success();
    }

    @ApiOperation("进入课程镜像配置修改实验镜像的桌面环境/刷新")
    @GetMapping("/{chapterId}/experiment")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    @PreAcquireLock(value = ENTER_EXPERIMENT_COURSE_IMAGE_ALLOCATION_KEY, timeout = ENTER_EXPERIMENT_TIME_OUT,
            message = ENTER_EXPERIMENT_LOCK_MESSAGE)
    public Result<List<ImageAllocationContainerVO>> enterExperiment(@PathVariable("chapterId") Long chapterId,
                                                                    @Autowired SpringSecurityUserInfoHolder userInfoHolder) {
        return super.enterExperiment(chapterId);
    }

    @ApiOperation("初始化课程镜像配置修改实验镜像的桌面环境")
    @GetMapping("/{chapterId}/experiment/init")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    @PreAcquireLock(value = ENTER_EXPERIMENT_COURSE_IMAGE_ALLOCATION_KEY, timeout = ENTER_EXPERIMENT_TIME_OUT,
            message = ENTER_EXPERIMENT_LOCK_MESSAGE)
    public Result<List<ImageAllocationContainerVO>> initExperiment(@PathVariable("chapterId") Long chapterId,
                                                                   @Autowired SpringSecurityUserInfoHolder userInfoHolder) {
        return super.initExperiment(chapterId);
    }

    @ApiOperation("课程修改镜像分配中的某个镜像")
    @PutMapping("/{chapterId}")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result updateImage(@PathVariable("chapterId") Long chapterId,
                              @RequestBody @Valid ImageAllocationImageUpdatePO imageAllocationImageUpdatePO) {
        return super.updateImage(chapterId, imageAllocationImageUpdatePO);
    }

    @ApiOperation("查询课程镜像分配列表")
    @GetMapping("/{courseId}")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result<List<ImageAllocationCourseVO>> listImageAllocations(@PathVariable("courseId") Long courseId) {
        List<ImageAllocationCourseVO> imageAllocationCourseVOS = imageAllocationService.listCourseImageAllocation(courseId);
        return Result.success(imageAllocationCourseVOS);
    }

    @Override
    protected ContainerContext getContainerContext(Long userId, Long taskId) {
        return new ContainerContext()
                .setUserId(userId)
                .setContextType(COURSE_IMAGE_ALLOCATION.getCode())
                .setContextId(taskId);
    }

    @Override
    protected ExperimentContext getExperimentContext(Long userId, Long taskId) {
        return new ExperimentContext()
                .setUserId(userId)
                .setContextType(COURSE_IMAGE_ALLOCATION.getCode())
                .setContextId(taskId);
    }

    @Override
    protected Integer getImageAllocationContextType() {
        return TASK.getCode();
    }
}
